package qgs.zisu.javaconcurrency.javaconcurrency.chapter9_ThreadCommunication;

/**
 * @Author: 蔡翔
 * @Date: 2019/10/12 20:19
 * @Version 1.0
 *
 * 单一生产者和 单一消费者  在多线程条件下保持顺序 消费。
 */
public class ProduceConsumerVersion2 {
    private int i = 0;
    final private Object LOCK = new Object();

    //volatile 是共享变量
    //共享变量：共享变量是指可以同时被多个线程访问的变量，共享变量是被存放在堆里面，所有的方法内临时变量都不是共享变量。
    private volatile boolean isProduced = false;

    public void produce(){
        synchronized (LOCK){
            if(isProduced){
                // 如果已近被生产过了，别人还没有消费，那就不要生产了
                try {
                    //这个线程会一直等待，直到别的线程影响了它。
                    LOCK.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else {
                i++;
                System.out.println("p->"+i);
                // 我这里已经生产好了，通知“别的线程去消费”
                LOCK.notify();
                isProduced = true;
            }

        }
    }

    public void consume(){
        synchronized (LOCK){
            if(isProduced){
                System.out.println("C->"+i);
                // 通知它，我已近消费了。可以再次生产了。
                LOCK.notify();
                isProduced = false;
            }else {
                try {
                    //没有生产，那么我现在得等，让锁等
                    LOCK.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        ProduceConsumerVersion2 pc = new ProduceConsumerVersion2();



        new Thread("Produce"){
            @Override
            public void run(){
                while (true){
                    pc.produce();
                }
            }
        }.start();

        new Thread("Consumer"){
            @Override
            public void run(){
                while (true){
                    pc.consume();
                }
            }
        }.start();

        /**
         * 结果：
         * p->159618
         * C->159618
         * p->159619
         * C->159619
         * p->159620
         * C->159620
         * p->159621
         *
         * 这样就能合理 消费了。生产出一个消费一个，不至于生产一个消费100个
         * 当然也可以把isProduced 设置成10，就试试生产10个消费10个
         * */
    }

}
